# Copyright (c) 2008 Alvin Wang http://cloudwizard.com/
# License New BSD
# See README for additional information

"""
Amazon Web Services Cloud Support

"""

from cloudwizard.ssh import Connection
from cloudwizard.compute import ComputeService
from cloudwizard.compute import ComputeDevice
from cloudwizard.config import Config
from api import GoGridClient
import time

class Compute(ComputeService):	# encapsulate connection
    """ComputeService API - Gogrid
    """

    def __init__(self, auth=None, username='default', **args):
        if auth:
            self.cloud_auth=auth
        else:
            self.cloud_auth = Config( cloud_abbrev = 'gogrid', config_name=username)
        self.cloud_obj = GoGridClient(key=self.cloud_auth.data['apikey'],
            secret=self.cloud_auth.data['apisecret'])
        #print self.cloud_obj.sendAPIRequest("grid/server/list")
        #print self.cloud_obj.sendAPIRequest("grid/server/list",{'format':'xml'})

    def olist(self, server_type=None):
        """list all servers as objects"""
        result = self.cloud_obj.request("grid/server/list")
        return result['list']
        
    def plist(self):
        """Print all servers as objects"""
        servers = self.olist()
        for server in servers:
            print server

    def create(self, name='default server', image='rhel44_32_lamp', ram='512MB',
        ip=None, description='Description of server'):
        """Create a server"""
        if ip  == None:         
            iplist = self.gogrid_ip_list( typename='public', statename='Unassigned')
            ip = iplist[0]['ip']
        params={'name':name, 'image':image, 'ram':ram, 'ip':ip,
            'description':description}
        result = self.cloud_obj.request("grid/server/add", params=params)
        ipaddr = result['list'][0]['ip']['ip']
        return GoGridServer( cloud_auth=self.cloud_auth, ip=ipaddr, name=name, 
            obj=result['list'])
        
    def find(self, name=None, id=None, ip=None):
        """return a GogridServer object"""
        return GoGridServer( cloud_auth=self.cloud_auth, ip=ip, name=name, 
            id=id)



    def delete(self, name=None, id=None):
        """Delete a server"""
        if id:
            params={'id':id}
            result = self.cloud_obj.request("grid/server/delete", params=params)
            return result['list']        
        if name:
            params={'name':name}
            result = self.cloud_obj.request("grid/server/delete", params=params)
            return result['list']

    def deleteall(self):
        """Delete all servers"""
        servers = self.olist()
        for server in servers:
            print server

    def status(self, name=None, id=None):
        """return server status"""
        if id:
            print "id=",id
            params={'id':id}
            result = self.cloud_obj.request("grid/server/get", params=params)
            return result['list']
        if name:
            print "name=",name
            params={'name':name}
            result = self.cloud_obj.request("grid/server/get", params=params)
            return result['list']
        
    def reboot(self, name=None, id=None):
        """Reboot a server"""
        if name:
            params={'name':name,'power':'cycle'}
            result = self.cloud_obj.request("grid/server/power", params=params)
            return result['list']
        if id:
            params={'id':id,'power':'cycle'}
            result = self.cloud_obj.request("grid/server/power", params=params)
            return result['list']

    #################### Load Balancers #################################

    def lb_olist(self,):
        """list all load balancerss as objects"""     
        result = self.cloud_obj.request("grid/loadbalancer/list")
        return result['list']
        
    def lb_plist(self):
        """Print all servers as objects"""
        servers = self.olist()
        for server in servers:
            print server

    def lb_create(self, name='default LB', type=None,persistence=None,
        realip=[],realport=[], description='Description of load balancer',
        ip=None, port=None):
        """Create a Load balancer"""
        if ip  == None:         
            iplist = self.gogrid_ip_list( typename='public', statename='Unassigned')
            ip = iplist[0]['ip']
        params={'name':name, 'image':image, 'ram':ram, 'ip':ip,
            'description':description}
        result = self.cloud_obj.request("grid/loadbalancer/add", params=params)
        return result['list']
        
    def lb_delete(self, name=None, id=None):
        """Delete a server"""
        if id:
            params={'id':id}
            result = self.cloud_obj.request("grid/loadbalancer/delete", params=params)
            return result['list']        
        if name:
            params={'name':name}
            result = self.cloud_obj.request("grid/loadbalancer/delete", params=params)
            return result['list']

    def lb_deleteall(self):
        """Delete all servers"""
        servers = self.olist()
        for server in servers:
            print server

    def lb_status(self, name=None, id=None):
        """Create a server"""
        if id:
            params={'id':id}
            result = self.cloud_obj.request("grid/loadbalancer/get", params=params)
            return result['list']
        if name:
            params={'name':name}
            result = self.cloud_obj.request("grid/loadbalancer/get", params=params)
            return result['list']
        
    
    #########################################################################
    
    def gogrid_olist_loadbalancers(self):
        """list all Load Balancers as objects"""
        result = self.cloud_obj.request("grid/loadbalancer/list")
        return result['list']
        
    def gogrid_plist_loadbalancers(self):
        """Print all GoGrid Images"""
        images = self.gogrid_olist_loadbalancers()
        
        for image in images:
            print image['friendlyName'], image['description']
            """
            {u'isPublic': True, u'name': u'centos44_32_apache22php5', u'object': u'serverimage', u'location': u'centos44_32_apache22php5_', u'friendlyName': u'CentOS 4.4 (32-bit) w/ Apache 2.2 + PHP5', u'id': 1, u'isActive': True, u'description': u'CentOS 4.4 (32-bit) w/ Apache 2.2 + PHP5'}
            """
    #########################################################################
    
    def gogrid_olist_images(self, status=None, reservation=None):
        """list all GoGrid Images as objects"""
        result = self.cloud_obj.request("grid/image/list")
        return result['list']
        
    def gogrid_plist_images(self, status=None, reservation=None):
        """Print all GoGrid Images"""
        images = self.gogrid_olist_images()
        
        for image in images:
            print image['name'], image['description']
            """
            {u'isPublic': True, u'name': u'centos44_32_apache22php5', u'object': u'serverimage', u'location': u'centos44_32_apache22php5_', u'friendlyName': u'CentOS 4.4 (32-bit) w/ Apache 2.2 + PHP5', u'id': 1, u'isActive': True, u'description': u'CentOS 4.4 (32-bit) w/ Apache 2.2 + PHP5'}
            """

    #########################################################################

    def gogrid_ip_list(self, typename='all', statename=None):
        """list IPs"""
        if typename == 'all':
            result = self.cloud_obj.request("grid/ip/list")
            if statename == None:
                result = self.cloud_obj.request("grid/ip/list")
            elif statename == 'Unassigned':
                result = self.cloud_obj.request("grid/ip/list", 
                    params={'ip.state':'unassigned'})
            elif statename == 'Ussigned':
                result = self.cloud_obj.request("grid/ip/list", 
                    params={ 'ip.state':'unassigned'})
            else:
                print "ip.state can only be Assigned or Unassigned"
                return []        
        elif typename == 'public':
            if statename == None:
                result = self.cloud_obj.request("grid/ip/list",params={'ip.type':'Public'})
            elif statename == 'Unassigned':
                result = self.cloud_obj.request("grid/ip/list", 
                    params={'ip.type':'Public', 'ip.state':'unassigned'})
            elif statename == 'Ussigned':
                result = self.cloud_obj.request("grid/ip/list", 
                    params={'ip.type':'Public', 'ip.state':'unassigned'})
            else:
                print "ip.state can only be Assigned or Unassigned"
                return []        
        elif typename == 'private':
            if statename == None:
                result = self.cloud_obj.request("grid/ip/list",params={'ip.type':'Private'})
            elif statename == 'Unassigned':
                result = self.cloud_obj.request("grid/ip/list", 
                    params={'ip.type':'Private', 'ip.state':'unassigned'})
            elif statename == 'Ussigned':
                result = self.cloud_obj.request("grid/ip/list", 
                    params={'ip.type':'Private', 'ip.state':'unassigned'})
            else:
                print "ip.state can only be Assigned or Unassigned"
                return []        
        else:
            print "type can only be public or private"
            return []        

        return result['list']

class GoGridServer(ComputeDevice):
    """A compute device is a CPU.  There is usually some disk included."""
    cloud_user = None
    cloud_password = None
    cloud_keyfile = None
    cloud_ip_address = None
    gogrid_name = None
    gogrid_id = None
    gogrid_ip = None
    gogrid_obj = None
    
    def __init__(self, cloud_auth, id=None, ip=None, name=None,obj=None):  # set variables
        """Initialize Device"""
        self.cloud_auth = cloud_auth
        self.cloud_obj = GoGridClient(key=self.cloud_auth.data['apikey'],
            secret=self.cloud_auth.data['apisecret'])

        if id:
            self.gogrid_id = id
        if name:
            self.gogrid_name = name
        if ip:
            self.gogrid_ip = ip
        if obj:
            self.gogrid_obj = obj

    def wait_status(self):
        # status - disk file, ec2
        if gogrid_id:        
            params={'id':id}
            result = self.cloud_obj.request("grid/server/get", params=params)
            return result['list']

    def status(self):
        # status - disk file, ec2
        if self.gogrid_id:        
            params={'id':self.gogrid_id}
            result = self.cloud_obj.request("grid/server/get", params=params)
            self.gogrid_ip = result['list'][0]['ip']['ip']
            return result['list']
        params={'name':self.gogrid_name}
        result = self.cloud_obj.request("grid/server/get", params=params)
        return result['list']

    def get_ip(self):
        """Return IP"""
        if self.gogrid_ip:
            return self.gogrid_ip
            
    def get_password(self):
        """Return IP"""
        result = self.cloud_obj.request("support/password/list")
        passwords = result['list']
        for password in passwords:
            if password.has_key('server'):
                server = password['server']
                if str(server['id']) == self.gogrid_id.strip():
                    return password['password']
        return None
        
    def wait_for_start(self, timelimit=600, printdot=False):
        """Wait until state == 1"""
        # status - disk file, ec2
        i=0
        while i < timelimit:
            result = self.status()
            if result[0]['state']['id'] == 1:
                return True
            time.sleep(1)
            i+=1
            if printdot:
                print '.',
        return False

    def get_ssh(self):
        """Get the ssh connection object
        """     
        self.status()
        if self.gogrid_id:        
            password = self.get_password()
            print "password is", password
            return Connection(self.gogrid_ip, username='root', 
                password=password)
        else:
            print "System not ready"
            
    def delete(self):
        """Delete a server"""
        params={'id':self.gogrid_id}
        result = self.cloud_obj.request("grid/server/delete", params=params)
        return result['list']        
            